from Portfolio.Portfolio import Portfolio
from Misc.QuoteType import QuoteType
from datetime import timedelta
import numpy as np
import matplotlib.pyplot as plt

class PerfMeasure:
	
	def __init__(self, obeserve_times, portfolio, quote_type=QuoteType.CLOSE, currency=None):
	
		self.portf = portfolio
		self.portf_nav_series = []
		
		for t in obeserve_times:
			self.portf_nav_series.append((t, portfolio.nav(t, quote_type, currency)))
			
		self.portf_nav_series.sort()

	def portfolio(self):
		return self.portf
	
	def nav_series(self): #[(ref_time, nav)]
		return self.portf_nav_series
		
	def return_series(self): #[return]
		
		return_series = []
		
		for i in range(1, len(self.portf_nav_series)):		
			return_series.append(self.portf_nav_series[i][1]/self.portf_nav_series[i-1][1] - 1)
			
		return return_series
		
	def annulized_return(self):
	
		DAY_COUNT_BASIS = 365.0
		year_frc = (self.portf_nav_series[-1][0] - self.portf_nav_series[0][0]).days/DAY_COUNT_BASIS
		#end_value = start_value*(1+annulized_return)^year_frc
		return pow(self.portf_nav_series[-1][1]/self.portf_nav_series[0][1], 1/year_frc) - 1
		
	def max_return(self):
		return np.max(self.return_series())
		
	def min_return(self):
		return np.min(self.return_series())
		
	def mean_return(self):
		return np.mean(self.return_series())
		
	def std_return(self):
		return np.std(self.return_series())
		
	def max_drowdown(self):
		
		drowdown = [0, timedelta(0)] #(down_rate, down_period)
	
		length = len(self.portf_nav_series)
		
		for i in range(length):
		
			for j in range(i + 1, length):
			    
				r = self.portf_nav_series[j][1]/self.portf_nav_series[i][1] - 1
				period = self.portf_nav_series[j][0] - self.portf_nav_series[i][0]
				#replace drowdown if the worse was found
				if r < drowdown[0]:
					drowdown[0] = r 
					drowdown[1] = period
		
		return (drowdown[0], str(drowdown[1])) #(down_rate, _str_down_period)
		
	def mean_return_large_zero(self):
		return np.mean([r for r in self.return_series() if r > 0])
		
	def mean_return_less_zero(self):
		return np.mean([r for r in self.return_series() if r < 0])
		
	def win_rate(self):
	
		return float(len([r for r in self.return_series() if r > 0]))/float(len(self.return_series()))
		
	def nav_plot(self, save_path = None):
	
		xaxis = [each[0] for each in self.portf_nav_series]
		yaxis = [each[1] for each in self.portf_nav_series]
		plt.xlabel('Time')
		plt.ylabel('NAV')
		plt.plot(xaxis,yaxis)
		plt.show()	
		if save_path:
			plt.savefig(save_path + '.pdf') 
		
	def return_plot(self, save_path = None):
	
		xaxis = []
		for i in range(1, len(self.portf_nav_series)):
			xaxis.append(self.portf_nav_series[i][0])
		yaxis = self.return_series()
		plt.xlabel('Time')
		plt.ylabel('Return')
		plt.bar(xaxis, yaxis)
		plt.show()	
		if save_path:
			plt.savefig(save_path + '.pdf')  
		
	def perf_statistics(self):
	
		return np.array([['ANNULIZED_RETURN', self.annulized_return()],
						['MAX_RETURN', self.max_return()],
						['MIN_RETURN', self.min_return()],
						['MEAN_RETURN', self.mean_return()],
						['STD_RETURN', self.std_return()],
						['MAX_DROWDOWN_RATE', self.max_drowdown()[0]],
						['MAX_DROWDOWN_PERIOD', self.max_drowdown()[1]],
						['MEAN_RETURN >0', self.mean_return_large_zero()],
						['MEAN_RETURN <0', self.mean_return_less_zero()],
						['WIN_RATE', self.win_rate()]])
				
		
				
		
		
	
		

		